package cn.tedu.mall.seckill.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuDetailSimpleVO;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuVO;
import cn.tedu.mall.seckill.service.ISeckillSpuService;
import cn.tedu.mall.seckill.utils.RedisBloomUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class SeckillSpuServiceImpl implements ISeckillSpuService {
    @Autowired
    private RedisTemplate redisTemplate;
    public static final String SECKILL_SPUS_KEY="sekill:spus";
    public static final String SECKILL_SPU_PREFIX="sekill:spu:";
    @Override
    public JsonPage<SeckillSpuVO> listSeckillSpus(Integer page, Integer pageSize) {
        //所有数据查询 在秒杀都走缓存
        List<SeckillSpuVO> spus= (List<SeckillSpuVO>) redisTemplate.opsForValue().get(SECKILL_SPUS_KEY);
        //简单判断一下
        if (spus==null||spus.size()==0){
            throw
                    new CoolSharkServiceException
                            (ResponseCode.NOT_FOUND,"当前缓存没有数据,请检查预热逻辑");
        }
        return JsonPage.defaultPage(spus);
    }

    //添加布隆过滤器 判断spuId是否存在,存在,才继续,不存在直接抛异常
    @Autowired
    private RedisBloomUtils redisBloomUtils;
    //定义布隆过滤器,存储所有spuId的key值
    public static final String SECKILL_BLOOM_SPUS_KEY="seckill:bloom:spus";
    @Override
    public SeckillSpuVO getSeckillSpu(Long spuId) {
        Boolean exists = redisBloomUtils.bfexists(SECKILL_BLOOM_SPUS_KEY, spuId + "");
        if (!exists){
            throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,
                    "当前数据中没有spuId:"+spuId);
        }
        SeckillSpuVO seckillSpuVO
                = (SeckillSpuVO) redisTemplate.opsForValue().get(SECKILL_SPU_PREFIX+spuId);
        if (seckillSpuVO == null){
            throw
                    new CoolSharkServiceException
                            (ResponseCode.NOT_FOUND,"当前缓存没有数据,请检查预热逻辑");
        }
        //判断当前系统时间,是否在秒杀时间段内,如果不在时间段,url不带回去
        LocalDateTime now= LocalDateTime.now();
        Duration afterStart
                = Duration.between(now, seckillSpuVO.getStartTime());
        Duration beforEnd
                = Duration.between(seckillSpuVO.getEndTime(), now);
        //根据between方法解释,定义获取时间对比值afterStart now>start
        // beforEnd end>now 两个条件有一个不满足,说明秒杀时间和当前系统时间不匹配
        if (!(afterStart.isNegative() && beforEnd.isNegative())){
            //时间不合法,url不要带
            seckillSpuVO.setUrl(null);
        }
        return seckillSpuVO;
    }

    @Override
    public SeckillSpuDetailSimpleVO getSeckillSpuDetail(Long spuId) {
        return null;
    }
}
